package cn.jdemo.juc.brief.sdk.bean.copier.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

import cn.jdemo.juc.brief.sdk.bean.copier.provider.CopyEntity;


/**
 * 
 * @DESC BeanCopy工具类
 * @author zhangliuwei
 *
 */
public class BeanCopyUtil {

	/**
	 * @desc 原实体类相关字段值赋值到目标字段中
	 * 		 1) 针对字段无法一一对应
	 * 		 2) 针对字段对应后字段类型不匹配
	 *       3) dest对象中存放所需结果
	 * @param source
	 * @param dest
	 * @throws Exception
	 */
	public static void beanCopy(Object source, Object dest) throws Exception {
		new CopyEntity(source, dest).convertToBean();
	}
	public static String date2String(Date date) {
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }


	/**
	 * @desc 获取指定字段的getter方法
	 * @param beanClass
	 * @param field
	 * @return
	 */
	public static Method getGetterMethod(Class<?> beanClass, Field field) {
		Method[] methods = getMethods(beanClass);

		final String fieldName = field.getName();
		final Class<?> fieldType = field.getType();
		final boolean isBooeanField = isBoolean(fieldType);
		Method getter = null;
		// Method setter = null;
		String methodName;
		Class<?>[] parameterTypes;
		for (Method method : methods) {
			parameterTypes = method.getParameterTypes();
			if (parameterTypes.length > 1) {
				// 多于1个参数说明非Getter或Setter
				continue;
			}
			methodName = method.getName();
			if (parameterTypes.length == 0) {
				// 无参数，可能为Getter方法
				if (isMatchGetter(methodName, fieldName, isBooeanField)) {
					// 方法名与字段名匹配，则为Getter方法
					getter = method;
				}
			} else if (isMatchSetter(methodName, fieldName, isBooeanField)) {
				// 只有一个参数的情况下方法名与字段名对应匹配，则为Setter方法
				// setter = method;
				continue;
			}
			if (null != getter) {
				// 如果Getter和Setter方法都找到了，不再继续寻找
				break;
			}
		}
		return getter;
	}

	/**
	 * @desc 获取指定字段的setter方法
	 * @param beanClass
	 * @param field
	 * @return 
	 */
	public static Method getSetterMethod(Class<?> beanClass, Field field) {
		Method[] methods = getMethods(beanClass);
		final String fieldName = field.getName();
		final Class<?> fieldType = field.getType();
		final boolean isBooeanField = isBoolean(fieldType);
		// Method getter = null;
		Method setter = null;
		String methodName;
		Class<?>[] parameterTypes;

		for (Method method : methods) {
			parameterTypes = method.getParameterTypes();
			if (parameterTypes.length > 1) {
				// 多于1个参数说明非Getter或Setter
				continue;
			}
			methodName = method.getName();
			if (parameterTypes.length == 0) {
				// 无参数，可能为Getter方法
				if (isMatchGetter(methodName, fieldName, isBooeanField)) {
					// 方法名与字段名匹配，则为Getter方法
					// getter = method;
					continue;
				}
			} else if (isMatchSetter(methodName, fieldName, isBooeanField)) {
				// 只有一个参数的情况下方法名与字段名对应匹配，则为Setter方法
				setter = method;
			}
			if (null != setter) {
				// 如果Getter和Setter方法都找到了，不再继续寻找
				break;
			}
		}
		return setter;
	}

	/**
	 * 获取实例的所有字段
	 * 
	 * @param beanClass
	 * @return
	 * @throws SecurityException
	 */
	public static Field[] getFields(Class<?> beanClass) throws SecurityException {
		if (beanClass == null) {
			return null;
		}
		Field[] fields = beanClass.getDeclaredFields();
		return fields;
	}

	/**
	 * 获取实体的所有方法体
	 * 
	 * @param beanClass
	 * @return
	 * @throws SecurityException
	 */
	public static Method[] getMethods(Class<?> beanClass) throws SecurityException {
		if (beanClass == null) {
			return null;
		}
		Method[] methods = beanClass.getMethods();
		return methods;
	}

	public static boolean isBoolean(Class<?> clazz) {
		return (clazz == Boolean.class || clazz == boolean.class);
	}
	
	/**
	 * @desc 方法是否为Getter方法,匹配规则如下（忽略大小写）：
	 * <pre>
	 * 字段名    -》 方法名
	 * isName  -》 isName
	 * isName  -》 isIsName
	 * isName  -》 getIsName
	 * name     -》 isName
	 * name     -》 getName
	 * </pre>
	 * @param methodName
	 * @param fieldName
	 * @param isBooeanField
	 * @return 是否匹配
	 */
	public static boolean isMatchGetter(String methodName, String fieldName, boolean isBooeanField) {
		// 全部转为小写，忽略大小写比较
		methodName = methodName.toLowerCase();
		fieldName = fieldName.toLowerCase();
		if (false == methodName.startsWith("get") && false == methodName.startsWith("is")) {
			// 非标准Getter方法
			return false;
		}
		if ("getclass".equals(methodName)) {
			// 跳过getClass方法
			return false;
		}
		// 针对Boolean类型特殊检查
		if (isBooeanField) {
			if (fieldName.startsWith("is")) {
				// 字段已经是is开头
				if (methodName.equals(fieldName) // isName -》 isName
						|| methodName.equals("get" + fieldName)// isName -》 getIsName
						|| methodName.equals("is" + fieldName)// isName -》 isIsName
				) {
					return true;
				}
			} else if (methodName.equals("is" + fieldName)) {
				// 字段非is开头， name -》 isName
				return true;
			}
		}
		// 包括boolean的任何类型只有一种匹配情况：name -》 getName
		return methodName.equals("get" + fieldName);
	}

	/**
	 * @desc 方法是否为Setter方法, 匹配规则如下（忽略大小写）：
	 * <pre>
	 * 字段名    -》 方法名
	 * isName  -》 setName
	 * isName  -》 setIsName
	 * name     -》 setName
	 * </pre>
	 * @param methodName 方法名
	 * @param fieldName 字段名
	 * @param isBooeanField 是否为Boolean类型字段
	 * @return 是否匹配
	 */
	public static boolean isMatchSetter(String methodName, String fieldName, boolean isBooeanField) {
		// 全部转为小写，忽略大小写比较
		methodName = methodName.toLowerCase();
		fieldName = fieldName.toLowerCase();
		// 非标准Setter方法跳过
		if (false == methodName.startsWith("set")) {
			return false;
		}
		// 针对Boolean类型特殊检查
		if (isBooeanField && fieldName.startsWith("is")) {
			// 字段是is开头
			if (methodName.equals("set" + removePrefix(fieldName, "is"))// isName -》 setName
					|| methodName.equals("set" + fieldName)// isName -》 setIsName
			) {
				return true;
			}
		}
		// 包括boolean的任何类型只有一种匹配情况：name -》 setName
		return methodName.equals("set" + fieldName);
	}

	/**
	 * @desc 移除指定前缀
	 * @param str
	 * @param prefix
	 * @return
	 */
	public static String removePrefix(CharSequence str, CharSequence prefix) {
		if (isEmpty(str) || isEmpty(prefix)) {
			return str(str);
		}
		final String str2 = str.toString();
		if (str2.startsWith(prefix.toString())) {
			return subSuf(str2, prefix.length());// 截取后半段
		}
		return str2;
	}

	public static boolean isEmpty(CharSequence str) {
		return str == null || str.length() == 0;
	}

	public static String str(CharSequence cs) {
		return null == cs ? null : cs.toString();
	}

	public static String subSuf(CharSequence string, int fromIndex) {
		if (isEmpty(string)) {
			return null;
		}
		return sub(string, fromIndex, string.length());
	}

	/**
	 * 改进JDK subString<br>
	 * index从0开始计算，最后一个字符为-1<br>
	 * 如果from和to位置一样，返回 "" <br>
	 * 如果from或to为负数，则按照length从后向前数位置，如果绝对值大于字符串长度，则from归到0，to归到length<br>
	 * 如果经过修正的index中from大于to，则互换from和to example: <br>
	 * abcdefgh 2 3 =》 c <br>
	 * abcdefgh 2 -3 =》 cde <br>
	 *
	 * @param str
	 *            String
	 * @param fromIndex
	 *            开始的index（包括）
	 * @param toIndex
	 *            结束的index（不包括）
	 * @return 字串
	 */
	public static String sub(CharSequence str, int fromIndex, int toIndex) {
		if (isEmpty(str)) {
			return str(str);
		}
		int len = str.length();
		if (fromIndex < 0) {
			fromIndex = len + fromIndex;
			if (fromIndex < 0) {
				fromIndex = 0;
			}
		} else if (fromIndex > len) {
			fromIndex = len;
		}
		if (toIndex < 0) {
			toIndex = len + toIndex;
			if (toIndex < 0) {
				toIndex = len;
			}
		} else if (toIndex > len) {
			toIndex = len;
		}
		if (toIndex < fromIndex) {
			int tmp = fromIndex;
			fromIndex = toIndex;
			toIndex = tmp;
		}
		if (fromIndex == toIndex) {
			return "";
		}
		return str.toString().substring(fromIndex, toIndex);
	}
}
